package com.example.win.android_banduyujia.lib.datetime;

import com.example.win.android_banduyujia.lib.util.StrUtils;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;

/**
 * Created by huchun on 2015/8/9.
 */
public class DateTime implements Serializable{

    private static final long serialVersionUID = 100120110L;

    private static final int MILLISECEND_OF_MINUTE = 60*1000;
    private static final int MILLISECEND_OF_HOUR = 60*MILLISECEND_OF_MINUTE;
    private static final int MILLISECEND_OF_DAY = 24*MILLISECEND_OF_HOUR;
    private static final int MILLISECEND_OF_WEEK = 7*MILLISECEND_OF_DAY;
    private static final int MILLISECEND_OF_MONTH = 30*MILLISECEND_OF_DAY;
    private static final int MILLISECEND_OF_YEAR = 365*MILLISECEND_OF_DAY;

    private static final String TIMEZONE_UTC = "GMT";

    Calendar  mUTCCalendar;
    private Object UTCTimeInMillis;
    private int second;
    private int minute;
    private int hour;
    private int day;
    private int month;
    private int year;
    private Object localDayStr;
    private Object localMonthStr;
    private Object localYearStr;
    private int localMonth;
    private int localDay;

    public DateTime(){
        mUTCCalendar = Calendar.getInstance(TimeZone.getTimeZone(TIMEZONE_UTC));
    }

    public DateTime(Calendar calendar){
        mUTCCalendar = calendar;
    }

    public  DateTime(long utcTimeMilliseconds){
        mUTCCalendar = Calendar.getInstance(TimeZone.getTimeZone(TIMEZONE_UTC));
        mUTCCalendar.setTimeInMillis(utcTimeMilliseconds);
    }

    public DateTime(int year, int month, int day, int hour, int minute,int second, boolean isUTCParams){
        mUTCCalendar = Calendar.getInstance(TimeZone.getTimeZone(TIMEZONE_UTC));
        if(isUTCParams){
            setTimeElement(year, month, day, hour, minute, second);
        }else{
            Calendar calendar=Calendar.getInstance(TimeZone.getDefault());
            calendar.set(Calendar.YEAR, year);
            calendar.set(Calendar.MONTH, month-1);
            calendar.set(Calendar.DAY_OF_MONTH, day);
            calendar.set(Calendar.HOUR_OF_DAY, hour);
            calendar.set(Calendar.MINUTE, minute);
            calendar.set(Calendar.SECOND, second);

            mUTCCalendar.setTimeInMillis(calendar.getTimeInMillis());
            // 1、取得本地时间：
            // 2、取得时间偏移量：
            // int zoneOffset = calendar.get(java.util.Calendar.ZONE_OFFSET);
            // //3、取得夏令时差：
            // int dstOffset = calendar.get(java.util.Calendar.DST_OFFSET);
            // //4、从本地时间里扣除这些差量，即可以取得UTC时间+：
            // calendar.add(java.util.Calendar.MILLISECOND, -(zoneOffset +
            // dstOffset));
            // 之后调用cal.get(int x)或cal.getTimeInMillis()方法所取得的时间即是UTC标准时间。
        }
    }

    public DateTime(String clockTimeString, boolean isUTCString){
        mUTCCalendar = Calendar.getInstance(TimeZone.getTimeZone(TIMEZONE_UTC));
        fromString(clockTimeString, isUTCString);
    }

    public Calendar getLocalCalendar() {
        Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
        calendar.setTimeInMillis(getUTCTimeInMillis());
        return calendar;
    }

    public Calendar getUtcCalendar(){
        return mUTCCalendar;
    }

    private void setTimeElement(int year, int month, int day, int hour, int minute, int second) {
        setYear(year);
        setMonth(month);
        setDay(day);
        setHour(hour);
        setMinute(minute);
        setSecond(second);
    }

    public void setYear(int year) {
        mUTCCalendar.set(Calendar.YEAR, year);
    }

    public void setMonth(int month) {
        mUTCCalendar.set(Calendar.MONTH, month);
    }

    public void setDay(int day) {
        mUTCCalendar.set(Calendar.DAY_OF_MONTH, day);
    }

    public void setHour(int hour) {
        mUTCCalendar.set(Calendar.HOUR_OF_DAY, hour);
    }

    public void setMinute(int minute) {
        mUTCCalendar.set(Calendar.MINUTE, minute);
    }

    public void setSecond(int second) {
        mUTCCalendar.set(Calendar.SECOND, second);
    }

    public void addYearh(int diffYear){
        mUTCCalendar.add(Calendar.YEAR, diffYear);
    }

    public void addMonth(int diffMonth){
        mUTCCalendar.add(Calendar.MONTH, diffMonth);
    }

    public void addWeek(int diffWeek){
        mUTCCalendar.add(Calendar.WEEK_OF_MONTH, diffWeek);
    }

    public void addDay(int diffDay){
        mUTCCalendar.add(Calendar.DAY_OF_MONTH, diffDay);
    }

    public void addHour(int diffHour){
        mUTCCalendar.add(Calendar.HOUR_OF_DAY, diffHour);
    }

    public void addMinute(int diffMinute){
        mUTCCalendar.add(Calendar.MINUTE, diffMinute);
    }

    public void addSecond(int diffSecond){
        mUTCCalendar.add(Calendar.SECOND, diffSecond);
    }

    public int getLocalWeekBeginSunday(){
       Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
       calendar.setTimeInMillis(getUTCTimeInMillis());
       return calendar.get(Calendar.DAY_OF_WEEK);
    }

    public int getLocalWeekBeginMonday(){
        int curDayOfWeek = getLocalWeekBeginSunday();
        if(curDayOfWeek >=2){
            curDayOfWeek = curDayOfWeek - 1;
        }else{
            // 把周一调整到7计算
            curDayOfWeek = 7;
        }
        return curDayOfWeek;
    }

    public int getLocalYear(){
        Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
        calendar.setTimeInMillis(getUTCTimeInMillis());
        return calendar.get(Calendar.YEAR);
    }

    public String getLocalYearMonthDayStr() {
        return getLocalYearStr() + getLocalMonthStr() + getLocalDayStr();
    }

    public String getLocalYearStr() {
        int  localYear = getLocalYear();
        String  strYear = Integer.toString(localYear);
        if(localYear < 10){
            strYear = "0"+strYear;
        }
        return strYear;
    }

    public int getLocalMonth() {
        Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
        calendar.setTimeInMillis(getUTCTimeInMillis());
        // 月份是从0开始的, 用0来表示1月, 你如果想表示12月那就应该设置calendar.set(2011,11,31);
        return calendar.get(Calendar.MONTH)+1;
    }

    public String getLocalMonthStr() {
        int localMonth = getLocalMonth();
        String  strMonth = Integer.toString(localMonth);
        if(localMonth < 10 ){
            strMonth = "0" + strMonth;
        }
        return strMonth;
    }

    public int getLocalActualMaxMonth() {
        Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
        calendar.setTimeInMillis(getUTCTimeInMillis());
        // 月份是从0开始的, 用0来表示1月, 你如果想表示12月那就应该设置calendar.set(2011,11,31);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    public int getLocalDay() {
        Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
        calendar.setTimeInMillis(getUTCTimeInMillis());
        return calendar.get(Calendar.DAY_OF_MONTH);
    }

    public String getLocalDayStr() {
        int localDay = getLocalDay();
        String  strDay = Integer.toString(localDay);
        if(localDay < 10 ){
            strDay = "0" + strDay;
        }
        return strDay;
    }

    public String getLocalHourStr() {
        int localHour = getLocalHour();
        String  strHour = Integer.toString(localHour);
        if(localHour < 10 ){
            strHour = "0" + strHour;
        }
        return strHour;
    }

    public String getLocalMinuteStr() {
        int localMinute = getLocalMinute();
        String  strMinute = Integer.toString(localMinute);
        if(localDay < 10 ){
            strMinute = "0" + strMinute;
        }
        return strMinute;
    }

    public int getLocalHour() {
        Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
        calendar.setTimeInMillis(getUTCTimeInMillis());
        return calendar.get(Calendar.HOUR_OF_DAY);
    }

    public int getLocalMinute() {
        Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
        calendar.setTimeInMillis(getUTCTimeInMillis());
        return calendar.get(Calendar.MINUTE);
    }

    public int getLocalSecond() {
        Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
        calendar.setTimeInMillis(getUTCTimeInMillis());
        return calendar.get(Calendar.SECOND);
    }

    public int getUTCYear(){
        return mUTCCalendar.get(Calendar.YEAR);
    }

    public int getUTCMonth(){
        return mUTCCalendar.get(Calendar.MONTH);
    }

    public int getUTCActualMaxMonth(){
        return mUTCCalendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    public int getUTCDay(){
        return mUTCCalendar.get(Calendar.DAY_OF_MONTH);
    }

    public int getUTCHour(){
        return mUTCCalendar.get(Calendar.HOUR_OF_DAY);
    }

    public int getUTCMinute(){
        return mUTCCalendar.get(Calendar.MINUTE);
    }

    public int getUTCSecond(){
        return mUTCCalendar.get(Calendar.SECOND);
    }

    private boolean fromString(String clockTimeString, boolean isUTCString) {
        boolean success = false;
        int year = 0;
        int month = 0;
        int day = 0;
        int hour = 0;
        int minute = 0;
        int second = 0;

        if (StrUtils.isEmpty(clockTimeString)) {
            return false;
        }

        clockTimeString.replace("年", "-");
        clockTimeString.replace("月", "-");
        clockTimeString.replace("日", "");
        clockTimeString.replace("号", "");

        clockTimeString.replace("周一", "");
        clockTimeString.replace("周二", "");
        clockTimeString.replace("周三", "");
        clockTimeString.replace("周四", "");
        clockTimeString.replace("周五", "");
        clockTimeString.replace("周六", "");
        clockTimeString.replace("周日", "");
        clockTimeString.replace("星期一", "");
        clockTimeString.replace("星期二", "");
        clockTimeString.replace("星期三", "");
        clockTimeString.replace("星期四", "");
        clockTimeString.replace("星期五", "");
        clockTimeString.replace("星期六", "");
        clockTimeString.replace("星期日", "");

        if (clockTimeString.indexOf("-") >= 0) // at least "yyyy-mm-dd"
        {
            try {
                String[] sections = clockTimeString.split(" ");
                if (sections.length > 0) {
                    String[] tokens = StrUtils.split(sections[0], '-');
                    if (tokens.length == 3) {
                        year = StrUtils.toInt(tokens[0], 0);
                        month = StrUtils.toInt(tokens[1], 0);
                        day = StrUtils.toInt(tokens[2], 0);

                        success = true;
                    }
                    if (sections.length > 1) {
                        tokens = StrUtils.split(sections[1], ':');
                        if (tokens.length >= 2) {
                            hour = StrUtils.toInt(tokens[0], 0);
                            minute = StrUtils.toInt(tokens[1], 0);

                            if (tokens.length >= 3) {
                                second = StrUtils.toInt(tokens[2], 0);
                            }
                        }
                    }
                }
            } catch (NumberFormatException ex) {
                System.err.println(ex.getMessage());
            }

            if (isUTCString) {
                setTimeElement(year, month, day, hour, minute, second);
            } else {
                Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
                calendar.set(Calendar.YEAR, year);
                calendar.set(Calendar.MONTH, month - 1);
                calendar.set(Calendar.DAY_OF_MONTH, day);
                calendar.set(Calendar.HOUR_OF_DAY, hour);
                calendar.set(Calendar.MINUTE, minute);
                calendar.set(Calendar.SECOND, second);
                // 之后调用cal.get(int x)或cal.getTimeInMillis()方法所取得的时间即是UTC标准时间。

                mUTCCalendar.setTimeInMillis(calendar.getTimeInMillis());
            }
        } else {
            setUTCTimeInMillis(StrUtils.toLong(clockTimeString, 0));
        }
        return success;
    }

    public static DateTime now(){
        return new DateTime();
    }

    public long getUTCTimeInMillis() {
        return mUTCCalendar.getTimeInMillis();
    }

    public void setUTCTimeInMillis(long  millisseconds) {
        mUTCCalendar.setTimeInMillis(millisseconds);
    }

    public long getLocalTimeInMillis() {
        return getLocalCalendar().getTimeInMillis();
    }

    @Override
    public String toString() {
        return toLocalUniversalString();
    }

    public String toUTCString(String format){
        SimpleDateFormat  simpleDateFormat = new SimpleDateFormat(format);
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
        return simpleDateFormat.format(mUTCCalendar.getTime());
    }

    public String toUTCUniversalString(){
        SimpleDateFormat  simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
        return simpleDateFormat.format(mUTCCalendar.getTime());
    }

    public String toLocalString(String format){
        SimpleDateFormat  simpleDateFormat = new SimpleDateFormat(format);
        simpleDateFormat.setTimeZone(TimeZone.getDefault());
        return simpleDateFormat.format(mUTCCalendar.getTime());
    }

    private String toLocalUniversalString() {
        SimpleDateFormat  simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        simpleDateFormat.setTimeZone(TimeZone.getDefault());
        return simpleDateFormat.format(mUTCCalendar.getTime());
    }

    public DateTime getUTCDayStart(){
        DateTime dt = new DateTime(getUTCYear() , getUTCMonth(), getUTCDay(), 24, 0, 0, false);
        return  dt;
    }

    public DateTime getLocalDayStart(){
        DateTime dt = new DateTime(getLocalYear()-1 , getLocalMonth()-1, getLocalDay(), 0, 0, 0, true);
        return  dt;
    }

    public DateTime getLocalDayEnd(){
        DateTime dt = new DateTime(getLocalYear()-1 , getLocalMonth()-1, getLocalDay(), 24, 0, 0, true);
        return  dt;
    }

    public boolean isSameDate(DateTime refDate){
        return (getLocalYear() == refDate.getLocalYear()) && (getLocalMonth() == refDate.getLocalMonth()) && (getLocalDay() == refDate.getLocalDay());
    }

    public boolean isEmpty(){
        return (getLocalYear() == 0) && (getLocalMonth() == 0) && (getLocalDay() == 0)
                && (getLocalHour() == 0) && (getLocalMinute() == 0) && (getLocalSecond() == 0);
    }

    public DateTime getMinusAdvacedTime(String advanceTimeStr){
        long advanceTimeMillis = 0;
        int hour  = 0;
        int minute = 0;
        if(advanceTimeStr.indexOf("-") >= 0){
            try{
                String[]    sections = advanceTimeStr.split("h");

                if(sections.length > 0){
                    String[]  tokens = StrUtils.split(sections[0], '-'); // 1h30m
                    if(tokens.length == 2){
                        hour = StrUtils.toInt(tokens[0], 0);
                        minute = StrUtils.toInt(sections[1].replace("m",""), 0);
                    }
                }
            }catch (NumberFormatException ex){
                System.err.println(ex.getMessage());
            }
        }
        advanceTimeMillis = (hour * 60 + minute) * 60 * 1000;
        return new DateTime(getUTCTimeInMillis() - advanceTimeMillis);
    }

    public long span(DateTime time){
        if(time == null){
            return getLocalTimeInMillis();
        }else{
            return getLocalTimeInMillis() - time.getLocalTimeInMillis();
        }
    }
}
